<template>
    <div>
        <div v-html="renderedText"></div>
        <el-icon v-if="loading" class="is-loading" size="20" color="#2442BF">
            <Loading />
        </el-icon>
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed, watch } from 'vue';
import MarkdownIt from 'markdown-it';
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-dark.css';
import {Loading} from "@element-plus/icons-vue";

const props = defineProps({
    text: {
        type: String,
        required: true,
    },
    speed: {
        type: Number,
        default: 100, // 每个字间隔，默认100毫秒
    },
    isStop: {
        type: Boolean,
        default: false,
    },
    cursor: {
        type: Boolean,
        default: true,
    },
    loading: {
        type: Boolean,
        default: false,
    },
});

const emit = defineEmits(['loadOver']);

const displayedText = ref('');
const cursorVisible = ref(true);
const state=reactive({
    cursorTimer:null,
})

// 初始化 Markdown 渲染器
const md = new MarkdownIt({
    html: true,
    linkify: true,
    typographer: true,
    breaks: true,
    highlight: function (str, lang) {
        if (lang && hljs.getLanguage(lang)) {
            try {
                return `<pre><code class="language-${lang} hljs">` +
                    hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
                    '</code></pre>';
            } catch (_) {}
        }
        return '<pre><code class="language-none hljs">' + MarkdownIt().utils.escapeHtml(str) + '</code></pre>';
    },
});

// 渲染文本并加上光标
const renderedText = computed(() => {
    return md.render(displayedText.value);
});

// 睡眠函数
const sleep = (ms: number) => {
    return new Promise(resolve => setTimeout(resolve, ms));
};

// 逐字打印文本
const typeText = async () => {
    const oldText = displayedText.value;
    const newText = props.text;

    const startIndex = oldText.length;
    let currentText = oldText;

    for (let i = startIndex; i < newText.length; i++) {
        if (props.isStop) {
            clearInterval(state.cursorTimer);
            cursorVisible.value = !cursorVisible.value;
            break;
        }
        currentText += newText[i];
        displayedText.value = currentText; // 只追加新内容
        await sleep(props.speed);
    }
};

// 光标闪烁
const blinkCursor = () => {
    if(props.isStop===true){
        clearInterval(state.cursorTimer);
        return;
    }
    if(cursorVisible.value){
        state.cursorTimer= setInterval(() => {
            cursorVisible.value = !cursorVisible.value;
        }, 500);
    }
};

// 监听文本变化，更新打印
watch(
    () => props.text,
    async (newText, oldText) => {
        if (newText !== oldText) {
            // 如果新的文本不一样，追加新的内容
            await typeText();
        } else if (!newText) {
            // 如果文本为空，停止光标闪烁并发送结束通知
            cursorVisible.value = false; // 不再显示光标
            clearInterval(state.cursorTimer);
            emit('loadOver', { status: true, copytext: displayedText.value });
        }
    },
    { immediate: true }
);

// 组件挂载时初始化光标闪烁
onMounted(() => {
    if (props.cursor) {
        blinkCursor();
    }
});
</script>

<style scoped>
/* 光标样式 */
.hljs::after {
    content: '';
}
</style>
